package com.ibeeking.found.common.db.aop;

import com.ibeeking.found.common.constants.HeaderNounConstant;
import com.ibeeking.found.common.db.annotation.EnableMultiTenancyDB;
import com.ibeeking.found.common.db.annotation.IgnoreDS;
import com.ibeeking.found.common.db.util.DataSourceUtils;
import com.ibeeking.found.common.response.ResponseCodeEnum;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.data.SpelUtils;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.mysql.cj.util.LogUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName DataSourceAop
 * @Description
 * @Author ibeeking
 * @Date 2020-11-05 11:32
 **/
@Aspect
@ConditionalOnBean(annotation = EnableMultiTenancyDB.class)
@Component
@Order(-1)
public class DataSourceAop {
    private static final Logger log = LoggerFactory.getLogger(DataSourceAop.class);

    @Pointcut("execution(* com.ibeeking..*.*Controller.*(..))")
    public void changeDSHandle() {
    }

    @Pointcut("execution(* org.jeec*.modules.jmreport.desreport.a.*.*(..))")
    public void changeJimuDSHandle() {
    }

    @Around(("changeDSHandle()"))
    public Object changeDSHandle(ProceedingJoinPoint point) throws Throwable {
        String tenantId = "";
        MethodSignature signature = (MethodSignature) point.getSignature();
        //忽略数据源
        IgnoreDS ignoreDS = signature.getMethod().getAnnotation(IgnoreDS.class);
        if (null != ignoreDS) {
            if (StringUtils.isBlank(ignoreDS.value())) {
                return point.proceed();
            } else {
                tenantId = SpelUtils.getAopElValue(point.getArgs(), signature.getMethod(), ignoreDS.value());
            }
        } else {
            //1.获取HttpServletRequest
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
            //2.获取租户id
            tenantId = request.getHeader(HeaderNounConstant.TENANT_ID);
            if (StringUtils.isEmpty(tenantId)) {
                //2.针对积木report获取租户id
                tenantId = request.getHeader(HeaderNounConstant.JM_TENANT_ID);
            }
        }
        if (StringUtils.isEmpty(tenantId)) {
           throw new BusinessException(ResponseCodeEnum.TENANT_ID_NOT_EXIST.getCode(), ResponseCodeEnum.TENANT_ID_NOT_EXIST.getMsg());
        }
        try {
            //切换数据源
            DataSourceUtils.loadDataSource(tenantId, DataSourceUtils.writeOrRead(point, signature));
            return point.proceed();
        } finally {
            //清除数据源
            DataSourceUtils.clear();
        }
    }

    @Around(("changeJimuDSHandle()"))
    public Object changeJimuDSHandle(ProceedingJoinPoint point) throws Throwable {
        String tenantId = "";
        MethodSignature signature = (MethodSignature) point.getSignature();
        //忽略数据源

        //1.获取HttpServletRequest
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        //2.获取租户id
        tenantId = request.getHeader(HeaderNounConstant.TENANT_ID);
        if (StringUtils.isEmpty(tenantId)) {
            //2.针对积木report获取租户id
            tenantId = request.getHeader(HeaderNounConstant.JM_TENANT_ID);
            if (StringUtils.isEmpty(tenantId)) {
                tenantId = request.getParameter("tenantId");
            }
        }
        if (StringUtils.isEmpty(tenantId)) {
            throw new BusinessException(ResponseCodeEnum.TENANT_ID_NOT_EXIST.getCode(), ResponseCodeEnum.TENANT_ID_NOT_EXIST.getMsg());
        }
        try {
            //切换数据源
            DataSourceUtils.loadDataSource(tenantId, DataSourceUtils.writeOrRead(point, signature));
            return point.proceed();
        } finally {
            //清除数据源
            DataSourceUtils.clear();
        }
    }
}
